// Decompiled with JetBrains decompiler
// Type: FibMatrix.Config.MetaRawContext
// Assembly: FMCommon, Version=1.0.8663.21262, Culture=neutral, PublicKeyToken=null
// MVID: 52773074-FB09-4BA0-8FA9-4782D11D6C17
// Assembly location: /Users/mac/work/RiverGame/com.rivergame.fmframework/Runtime/Plugins/FMCommon.dll

using LZ4;
using System;
using System.Collections.Generic;
using Unity.Collections.LowLevel.Unsafe;

namespace FibMatrix.Config
{
    public class MetaRawContext
    {
        private Dictionary<string, MetaPosStatus> _metaSetPosMap;
        private Dictionary<string, MetaPosStatus> _rawBytesPosMap;
        private bool _logPerformanceWarning;
        private string[] _uniqueStrs;
        private int[] _uniqueInts;
        private long[] _uniqueLongs;
        private float[] _uniqueFloats;
        private double[] _uniqueDoubles;

        public string[] uniqueStrs { get { return this._uniqueStrs; } }

        public int[] uniqueInts { get { return this._uniqueInts; } }

        public long[] uniqueLongs { get { return this._uniqueLongs; } }

        public float[] uniqueFloats { get { return this._uniqueFloats; } }

        public double[] uniqueDoubles { get { return this._uniqueDoubles; } }

        public MetaRawContext(string[] uniqueStrs,
            int[] uniqueInts,
            long[] uniqueLongs,
            float[] uniqueFloats,
            double[] uniqueDoubles,
            Dictionary<string, MetaPosStatus> metaSetPosMap,
            Dictionary<string, MetaPosStatus> rawBytesPosMap,
            bool logPerformanceWarning = true)
        {
            this._uniqueStrs = uniqueStrs;
            this._uniqueInts = uniqueInts;
            this._uniqueLongs = uniqueLongs;
            this._uniqueFloats = uniqueFloats;
            this._uniqueDoubles = uniqueDoubles;
            this._metaSetPosMap = metaSetPosMap;
            this._rawBytesPosMap = rawBytesPosMap;
            this._logPerformanceWarning = logPerformanceWarning;
        }

        public void Dispose()
        {
            if (this._metaSetPosMap != null) {
                this._metaSetPosMap.Clear();
                this._metaSetPosMap = (Dictionary<string, MetaPosStatus>)null;
            }
            if (this._rawBytesPosMap != null) {
                this._rawBytesPosMap.Clear();
                this._rawBytesPosMap = (Dictionary<string, MetaPosStatus>)null;
            }
            this._uniqueStrs = (string[])null;
            this._uniqueInts = (int[])null;
            this._uniqueLongs = (long[])null;
            this._uniqueFloats = (float[])null;
            this._uniqueDoubles = (double[])null;
        }

        public List<string> GetAllRawBytesNames()
        {
            return this._rawBytesPosMap == null ? new List<string>() : new List<string>((IEnumerable<string>)this._rawBytesPosMap.Keys);
        }

        public List<string> GetAllMetaNames()
        {
            return new List<string>((IEnumerable<string>)this._metaSetPosMap.Keys);
        }

        private byte[] DecodeBlock(byte[] buffer,
            bool delayMode,
            int pos,
            out int contentLength,
            out int offset)
        {
            offset = 0;
            byte[] numArray;
            if (((uint)buffer[pos] & 1U) > 0U) {
                int inputLength = ConfigFormatUtil.ReadInt32(buffer, pos + 1);
                contentLength = ConfigFormatUtil.ReadInt32(buffer, pos + 5);
                numArray = LZ4Codec.Decode(buffer, pos + 9, inputLength, contentLength);
            } else {
                contentLength = ConfigFormatUtil.ReadInt32(buffer, pos + 1);
                if (delayMode) {
                    numArray = new byte[contentLength];
                    Buffer.BlockCopy((Array)buffer, pos + 5, (Array)numArray, 0, contentLength);
                } else {
                    numArray = buffer;
                    offset = pos + 5;
                }
            }
            return numArray;
        }

        private static unsafe void MemoryCopy(byte* src,
            byte* dst,
            int copyBytes,
            ref int srcOffset,
            ref int dstOffset)
        {
            Buffer.MemoryCopy((void*)(src + srcOffset), (void*)(dst + dstOffset), (long)copyBytes, (long)copyBytes);
            srcOffset += copyBytes;
            dstOffset += copyBytes;
        }

        private unsafe byte[] CombinePatchAndSrc(byte[] src,
            int offset,
            int srcContentLength,
            byte[] patchSrc,
            int patchOffset,
            int patchContentLength)
        {
            int num1 = patchOffset;
            int ivalue = ConfigFormatUtil.ReadInt32(patchSrc, ref patchOffset);
            int num2 = ConfigFormatUtil.ReadInt32(patchSrc, ref patchOffset);
            int srcOffset1 = ConfigFormatUtil.ReadInt32(patchSrc, ref patchOffset);
            int copyBytes1 = ConfigFormatUtil.ReadInt32(patchSrc, ref patchOffset);
            int num3 = ConfigFormatUtil.ReadInt32(patchSrc, ref patchOffset);
            int num4 = ConfigFormatUtil.Read7BitEncodedInt(patchSrc, ref patchOffset);
            int num5 = ConfigFormatUtil.Read7BitEncodedInt(patchSrc, ref patchOffset);
            int num6 = patchOffset - num1;
            int num7 = ConfigFormatUtil.ReadInt32(src, offset + 1);
            int copyBytes2 = patchContentLength - num6 - num3 * 4;
            byte[] buffer = new byte[srcContentLength + (ivalue - num7) * 4 + copyBytes2];
            int index1 = 0;
            int index2 = offset;
            buffer[index1] = src[index2];
            int pos = index1 + 1;
            int num8 = index2 + 1;
            ConfigFormatUtil.Write(buffer, pos, ivalue);
            int srcOffset2 = num8 + 4;
            int dstOffset = pos + 4;
            byte[] numArray = buffer;
            var numArrayPtr= UnsafeUtility.PinGCArrayAndGetDataAddress(numArray, out ulong gcHandle);
            byte* dst = (buffer == null || numArray.Length == 0)? (byte*)null : (byte*)(numArrayPtr);
            fixed (byte* src1 = src)
                fixed (byte* src2 = patchSrc) {
                    int copyBytes3 = num2 - srcOffset2;
                    MetaRawContext.MemoryCopy(src1, dst, copyBytes3, ref srcOffset2, ref dstOffset);
                    if (num4 > 0) {
                        int copyBytes4 = num4 * 4;
                        MetaRawContext.MemoryCopy(src1, dst, copyBytes4, ref srcOffset2, ref dstOffset);
                    }
                    MetaRawContext.MemoryCopy(src2, dst, num3 * 4, ref patchOffset, ref dstOffset);
                    if (num5 > 0) {
                        int srcOffset3 = srcOffset2 + (num7 - num4 - num5) * 4;
                        int copyBytes4 = num5 * 4;
                        MetaRawContext.MemoryCopy(src1, dst, copyBytes4, ref srcOffset3, ref dstOffset);
                    }
                    ConfigFormatUtil.Write(buffer, dstOffset, copyBytes1 + copyBytes2);
                    dstOffset += 4;
                    MetaRawContext.MemoryCopy(src1, dst, copyBytes1, ref srcOffset1, ref dstOffset);
                    MetaRawContext.MemoryCopy(src2, dst, copyBytes2, ref patchOffset, ref dstOffset);
                }
            numArray = (byte[])null;
            return buffer;
        }

        public IMetaItemSet GetMetaItemSet(string name, bool delayMode)
        {
            MetaPosStatus metaPosStatus;
            if (!this._metaSetPosMap.TryGetValue(name, out metaPosStatus))
                return (IMetaItemSet)null;
            int offset1;
            byte[] buffer;
            if (metaPosStatus.patchPos < 0) {
                buffer = this.DecodeBlock(metaPosStatus.src, delayMode, metaPosStatus.pos, out int _, out offset1);
            } else {
                int contentLength1;
                byte[] src = this.DecodeBlock(metaPosStatus.src, false, metaPosStatus.pos, out contentLength1, out offset1);
                int contentLength2;
                int offset2;
                byte[] patchSrc = this.DecodeBlock(metaPosStatus.patchSrc, false, metaPosStatus.patchPos, out contentLength2, out offset2);
                buffer = this.CombinePatchAndSrc(src, offset1, contentLength1, patchSrc, offset2, contentLength2);
                offset1 = 0;
            }
            MetaItemHelper helper = new MetaItemHelper(buffer, offset1);
            MetaItemSet metaItemSet;
            switch (helper.idType) {
                case MetaIdType.Int:
                    metaItemSet = (MetaItemSet)new IntIdMetaSet(name);
                    break;
                case MetaIdType.String:
                    metaItemSet = (MetaItemSet)new StringIdMetaSet(name);
                    break;
                case MetaIdType.Long:
                    metaItemSet = (MetaItemSet)new LongIdMetaSet(name);
                    break;
                default: throw new Exception("Not support id type " + helper.idType.ToString());
            }
            metaItemSet.Initialize(helper, this._uniqueStrs, this._uniqueInts, this._uniqueLongs, this._uniqueFloats, this._uniqueDoubles, delayMode, this._logPerformanceWarning);
            return (IMetaItemSet)metaItemSet;
        }

        public byte[] GetRawBytes(string name)
        {
            MetaPosStatus metaPosStatus;
            return this._rawBytesPosMap.TryGetValue(name, out metaPosStatus) ? this.DecodeBlock(metaPosStatus.src, true, metaPosStatus.pos, out int _, out int _) : (byte[])null;
        }
    }
}
